package middleware

import (
	"encoding/gob"
	ijwt "gitee.com/chicken-c/go-learn/webook/internal/web/jwt"
	"github.com/gin-gonic/gin"
	"github.com/golang-jwt/jwt/v5"
	"github.com/redis/go-redis/v9"
	"net/http"
	"time"
)

type LoginMiddlewareJWTBuilder struct {
	paths  []string
	Client redis.Cmdable
	ijwt.Handler
}

func NEWLoginMiddlewareJWTBuilder(Client redis.Cmdable, jwtHdl ijwt.Handler) *LoginMiddlewareJWTBuilder {
	return &LoginMiddlewareJWTBuilder{
		paths:   []string{},
		Client:  Client,
		Handler: jwtHdl,
	}
}

func (mw *LoginMiddlewareJWTBuilder) Ignore(path string) *LoginMiddlewareJWTBuilder {
	mw.paths = append(mw.paths, path)
	return mw
}

// 登录状态检查
func (mw *LoginMiddlewareJWTBuilder) LoginCheck() gin.HandlerFunc {
	gob.Register(time.Now())
	return func(ctx *gin.Context) {
		for _, path := range mw.paths {
			if ctx.Request.URL.Path == path {
				return
			}
		}

		//提取token
		tokenStr := mw.ExtractToken(ctx)
		claims := ijwt.UserClaims{}
		token, err := jwt.ParseWithClaims(tokenStr, &claims, func(tk *jwt.Token) (interface{}, error) {
			return []byte(ijwt.AtKey), nil
		})
		if err != nil {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			return
		}
		if token == nil || !token.Valid {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			return
		}

		//去redis查看token是否已经无效
		ok, err := mw.CheckSession(ctx, claims.Ssid)
		//if err != nil {
		//	//redis故障了，那我们所有的请求都会被挡住。
		//这里可以有降级策略，当redis崩了,我们就不验证退出的token了
		//}

		//这里是true的话，就代表token已经无效了
		if ok {
			ctx.AbortWithStatus(http.StatusUnauthorized)
			return
		}

		//可以把claims设置，方便我们后续profile 和edit
		ctx.Set("user", claims)
	}
}
